using System;
using System.Collections.Generic;
using System.Data;
using Gtk;
using Sqlpager;

public partial class MainWindow: Gtk.Window
{	
	#region Members
	
	Gtk.Entry searchEntry;
	Gtk.Label lblResults;
	DbPage db;
	Gtk.ListStore store;
	string[] columnList;
	string sortedColumn;
	SortType sortedType;
	string table;
	string columns;
	int page;
	bool searching;
	
	class SearchObject{
		public string text;
		public string orderby;
		public int page;
	}
	
	#endregion
	
	#region Properties
	
	public DbPage Db {
		get{return db;}
		set{db = value;}
	}
	
	#endregion
	
	#region Constructor
	
	public MainWindow (): base (Gtk.WindowType.Toplevel)
	{
		Build ();
		BuildToolbar();
		
		table = "tickets";
		columns = "status,number,date,customer,"+
			"problem,ip,active";
		db = new DbMySql(table,columns);	
		sortedType = SortType.Ascending;
		
		// grid
		columnList = columns.Split(new char[]{','});
		sortedColumn = columnList[1];
		InitializeStore();
		
		// animation object for loading icon
		imgLoading.PixbufAnimation = 
			Gdk.PixbufAnimation.LoadFromResource("loading.gif");
		
		// status column
		treeview1.AppendColumn(new TreeViewColumn(
		       "", new Gtk.CellRendererPixbuf (), "pixbuf", 0));
		
		for(int i=0; i < columnList.Length; i++) {
			Gtk.TreeViewColumn column = new Gtk.TreeViewColumn ();
			column.Title = columnList[i];
			Gtk.CellRendererText cell = new Gtk.CellRendererText ();	
  			column.PackStart (cell, true);
			column.AddAttribute (cell, "text", i+1);
			column.Resizable = true;
			column.Clickable = true;
	        //column.SortIndicator = true;
			column.Clicked += 
				new System.EventHandler (OnColumnClicked);
			this.treeview1.AppendColumn (column);	
		}	
		treeview1.RowActivated += new RowActivatedHandler(OnDoubleClick);
		treeview1.FocusInEvent += new FocusInEventHandler(OnFocusIn);
		Search(1);
	}
	
	#endregion
	
	#region Private Methods
	
	void BuildToolbar()
	{
		// create better toolbar
		Gtk.HBox hbox = new Gtk.HBox();		
		searchEntry = new Gtk.Entry();
		searchEntry.KeyPressEvent += 
			new KeyPressEventHandler(SearchEntryKeyPress);
		ToolItem t = new ToolItem();
		hbox.PackStart(searchEntry,false,false,0);
		t.Add(hbox);
		toolbar1.Insert(t,0);	
		ToolItem tExpand = new ToolItem();
		tExpand.Expand = true;
		toolbar1.Insert(tExpand,4);	
		lblResults = new Gtk.Label("Results");
		ToolItem t2 = new ToolItem();
		t2.Add(lblResults);
		toolbar1.Insert(t2,7);	
		toolbar1.ShowAll();
	}
	
	string GetOrderBy()
	{
		return sortedColumn +" "+
			((sortedType == SortType.Ascending) ? 
			" asc":" desc");
	}
		
	void InitializeStore()
	{
		Type[] types = new System.Type[columnList.Length+1];
		types[0] = typeof(Gdk.Pixbuf); // status icon
		for(int i=1;i<=columnList.Length;i++)
			types[i] = typeof(string);			
		store = new Gtk.ListStore(types);		
	}
		
	Gtk.ListStore GetListStore(DataTable dt)
    {	
		store.Clear();
		if(dt!=null)
		{
			foreach(DataRow r in dt.Rows)
			{
				object[] values = new object[columnList.Length +1];
				values[0] = GetIcon(r[0].ToString());
				for(int i=0; i < columnList.Length; i++)		
				{
					switch(i){
					case 1: // number column, zero padd
						values[i+1] = 
							r[i].ToString().PadLeft(6, '0');
						break;
					case 6: // active or not
						values[i+1] = 
							(r[i].ToString()=="1")?"YES":"NO";
						break;
					default:
						values[i+1] = Cut(r[i].ToString(),15);
						break;
					}
				}
				store.AppendValues(values);			
			}
		}
		
        return store;   
    }
	
	Gdk.Pixbuf GetIcon(string status)
	{
		Gdk.Pixbuf icon = Gdk.Pixbuf.LoadFromResource("gray.png");	
		switch(status){
		case "open":
			icon = Gdk.Pixbuf.LoadFromResource("red.png");
			break;
		case "waiting":
			icon = Gdk.Pixbuf.LoadFromResource("yellow.png");
			break;
		case "working":
			icon = Gdk.Pixbuf.LoadFromResource("green.png");
			break;
		}
		return icon;
	}
	
	void SetToolbarBuscador()
    {
        lblResults.Text = db.FirstRecord + "-" + 
			db.LastRecord + "/" + db.Total;            
        if(db.LastRecord ==0)
            lblResults.Text = "No Results";
        if (searchEntry.Text != "")
            lblResults.Text += " (Filtered)";
        gotoFirstAction.Sensitive = db.FirstExists();
        goBackAction.Sensitive = db.PreviousExists();
        goForwardAction.Sensitive = db.NextExists();
        gotoLastAction.Sensitive = db.LastExists();
		removeAction.Sensitive = (GetSelectedID()<0)?false:true;
    }
	
	void Search(int page)
	{
		if(db.IsConnected && !searching)
		{
			Buscando(true);	
			System.Threading.Thread thread = 
				new System.Threading.Thread (new 
			    System.Threading.ParameterizedThreadStart (
			 	SecondThread));
			SearchObject search = new SearchObject();
			search.text = searchEntry.Text;
			search.orderby = GetOrderBy();
			search.page = page;
			thread.Start (search);
		}
		
	}
	void SecondThread (object o) 
	{		
		// long task...
		SearchObject s = (SearchObject)o;
		DataTable dt = db.Search(s.text, s.page, s.orderby);
		page = db.Page;
		//System.Threading.Thread.Sleep (2000);
		// long task finished, this is needed to access 
		// GUI components from other thread
		Gtk.Application.Invoke (delegate {			
        	treeview1.Model = GetListStore(dt);
			SetToolbarBuscador();	
        	Buscando(false);		
       	});
	}
	
    void Buscando(bool b)
    {
		imgLoading.Visible = b;
		lblLoading.Visible = b;
		toolbar1.Sensitive = !b;
		searching = b;
        if (!b) searchEntry.GrabFocus();
    }
	
	string Cut(string cadena,int digitos)
	{
		return (cadena.Length > digitos)?
			cadena.Substring(0,digitos)+"...":
			cadena;
	}
	
	#endregion
	
	#region Events
	
	void OnDoubleClick(object o,RowActivatedArgs args)
    {
		int number = GetSelectedID();
		Ticket ticket = (Ticket)db.Select(number);
        TicketForm t = new TicketForm(this,ticket);
		ResponseType response = (ResponseType)t.Run();
		if(response == ResponseType.Ok)
		{
			db.Update(t.Ticket);
			Search(page);
		}
		t.Destroy();
	}     
	
	void OnColumnClicked (object o, System.EventArgs args)
    {
		Gtk.TreeViewColumn column = (Gtk.TreeViewColumn)o;
		sortedType = 
			(column.SortOrder==SortType.Ascending)?
			SortType.Descending : SortType.Ascending;
		column.SortOrder = sortedType;
		sortedColumn = column.Title;
		foreach(TreeViewColumn c in treeview1.Columns)
			c.SortIndicator = false;
		column.SortIndicator = true;
		Search(page);		
	}
	
	[GLib.ConnectBefore ()]
	void SearchEntryKeyPress(object o, KeyPressEventArgs e)
	{
		if(e.Event.Key == Gdk.Key.Return)
			Search(1);
	}
	
	void OnDeleteEvent (object o, DeleteEventArgs a)
	{
		Application.Quit ();
		a.RetVal = true;
	}
	void OnGoFirstActivated 
		(object o, System.EventArgs e)
	{
		Search(1);	
	}
	void OnGoPreviousActivated 
		(object o, System.EventArgs e)
    {
		Search(db.PreviousPage());
    }      
    void OnGoNextActivated 
		(object o, System.EventArgs e)
    {
		 Search(db.NextPage());
    }
    void OnGoLastActivated
		(object o, System.EventArgs e)
    {
		 Search(db.LastPage());
    }
   	
	void OnFindActionActivated (object o, System.EventArgs e)
	{
		Search(1);
	}
	void OnQuitActivated (object o, System.EventArgs e)
   	{
		Application.Quit();
   	}

	void OnAddClick (object o, System.EventArgs e)
	{
		TicketForm t = new TicketForm(this,null);
		ResponseType response = (ResponseType)t.Run();
		if(response == ResponseType.Ok)
		{
			db.Insert(t.Ticket);
			this.Search(page);
		}
		t.Destroy();
	}
	
	void OnRemoveClick (object sender, System.EventArgs e)
	{
		int number = GetSelectedID();
		if(number < 0) 
			return;
		MessageDialog md = new MessageDialog (this, 
            DialogFlags.DestroyWithParent,
            MessageType.Question,  ButtonsType.YesNo,
		    false,
            "Delete selected record?\nYou cannot undo this action.");
   		ResponseType r = (ResponseType)md.Run();
		if(r == ResponseType.Yes)
		{
			db.Delete(number);
			this.Search(page);
		}
		md.Destroy();
		
			
	}	
	
	void OnAboutClick (object o, System.EventArgs e)
	{
		string platform = "";
		int p = (int) Environment.OSVersion.Platform;
        if ((p == 4) || (p == 128))
         	platform = "running on Unix\n";
        else
			platform = "running on Windows\n";
    
		MessageDialog md = new MessageDialog (this, 
            DialogFlags.DestroyWithParent,
            MessageType.Info,  ButtonsType.Ok,
		    true,
            "Sqlpager 1.0\n"+
		    "Mono Gtk# version "+platform+
		    "Example followed by the book: \"Ready for shipment\"\n"+
		  	"<a href=\"http://sqlpager.googlecode.com\">"+
		    "http://sqlpager.googlecode.com</a>");
   		md.Run ();
        md.Destroy();
	}

	void OnDatabaseClick(object o, System.EventArgs e)
	{
		DbForm f = new DbForm(this);
		ResponseType resp = (ResponseType)f.Run();
		if(resp == ResponseType.Ok)
			db = new DbMySql(table,columns);		
		f.Destroy();
	}
	
	void OnFocusIn(object o, FocusInEventArgs e)
	{
		removeAction.Sensitive = (GetSelectedID()>0) ? true : false;
	}
	
	int GetSelectedID()
	{
		int result = -1;
		try
		{
			TreeSelection selection = treeview1.Selection;
			TreeModel model;
        	TreeIter iter;
			if(selection.GetSelected(out model, out iter))
			{
				// 2 is the index of number column
				result = Convert.ToInt32(model.GetValue (iter, 2));
			}
		}catch{}
		return result;
	}
	
	#endregion

	
}
